package com.gitee.ywj1352.sharing.db;


import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;
import org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration;
import org.apache.shardingsphere.replicaquery.api.config.ReplicaQueryRuleConfiguration;
import org.apache.shardingsphere.replicaquery.api.config.rule.ReplicaQueryDataSourceRuleConfiguration;
import org.apache.shardingsphere.sharding.algorithm.sharding.inline.InlineShardingAlgorithm;
import org.apache.shardingsphere.sharding.algorithm.sharding.inline.InlineShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.keygen.KeyGenerateStrategyConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;

//@Configuration
//@ConditionalOnClass({ShardingSphereDataSourceFactory.class})
public class ShardingSphereDataSourceConfig {

    /**
     * 配置主从
     *
     * @param dataSource1
     * @param dataSource2
     * @return
     * @throws SQLException
     */
    @Bean("dynamicDataSource")
    public DataSource getDataSource(@Qualifier("master01") DataSource dataSource1, @Qualifier("slave") DataSource dataSource2) throws SQLException {
        ReplicaQueryDataSourceRuleConfiguration dataSourceConfig = new ReplicaQueryDataSourceRuleConfiguration(
                "demo_replica_query_ds", "demo_primary_ds",
                Arrays.asList("demo_replica_ds_0"), null);
        ReplicaQueryRuleConfiguration ruleConfig = new ReplicaQueryRuleConfiguration(Collections.singleton(dataSourceConfig), Collections.emptyMap());
        Map<String, DataSource> result = new HashMap<>(3, 1);
        result.put("demo_primary_ds", dataSource1);
        result.put("demo_replica_ds_0", dataSource2);
        return ShardingSphereDataSourceFactory.createDataSource(result, Collections.singleton(ruleConfig), new Properties());
    }

    @Bean("sharingDataSource")
    public DataSource getSharingDataSource(@Qualifier("master00") DataSource dataSource1, @Qualifier("master01") DataSource dataSource2) throws SQLException {
        // 配置真实数据源
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        dataSourceMap.put("sharing_db00", dataSource1);
        dataSourceMap.put("sharing_db01", dataSource2);

        // 配置 user 表规则
        ShardingTableRuleConfiguration userTableRuleConfig =
                new ShardingTableRuleConfiguration("user", "sharing_db0${0..1}.user${0..15}");
        userTableRuleConfig.setDatabaseShardingStrategy
                (new StandardShardingStrategyConfiguration("user_id", "dbShardingAlgorithm"));
        userTableRuleConfig.setTableShardingStrategy
                (new StandardShardingStrategyConfiguration("user_id", "tableShardingAlgorithm"));

        ShardingTableRuleConfiguration orderTableRuleConfig =
                new ShardingTableRuleConfiguration("orders", "sharing_db0${0..1}.orders${0..15}");
        orderTableRuleConfig.setDatabaseShardingStrategy
                (new StandardShardingStrategyConfiguration("user_id", "dbShardingAlgorithm"));
        orderTableRuleConfig.setTableShardingStrategy
                (new StandardShardingStrategyConfiguration("user_id", "tableShardingAlgorithm"));




        // 配置分片规则
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTables().add(userTableRuleConfig);
        shardingRuleConfig.getTables().add(orderTableRuleConfig);

        //shardingRuleConfig.setDefaultTableShardingStrategy();


        // 配置分库算法
        Properties dbShardingAlgorithmrProps = new Properties();
        dbShardingAlgorithmrProps.setProperty("algorithm-expression", "sharing_db0${user_id % 2}");
        // 配置分表算法
        Properties usertableShardingAlgorithmrProps = new Properties();
        usertableShardingAlgorithmrProps.setProperty("algorithm-expression", "user${user_id % 16}");
        Properties ordertableShardingAlgorithmrProps = new Properties();
        ordertableShardingAlgorithmrProps.setProperty("algorithm-expression","orders${user_id % 16}");


        //设置
        shardingRuleConfig.getShardingAlgorithms()
                .put("dbShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE", dbShardingAlgorithmrProps));
        shardingRuleConfig.getShardingAlgorithms()
                .put("userTableShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE", usertableShardingAlgorithmrProps));
        shardingRuleConfig.getShardingAlgorithms()
                .put("orderTableShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE", ordertableShardingAlgorithmrProps));


        // 创建 ShardingSphereDataSource
        DataSource dataSource = ShardingSphereDataSourceFactory
                .createDataSource(dataSourceMap, Collections.singleton(shardingRuleConfig), new Properties());
        return dataSource;
    }


}
